import { useMemo } from "react";
import { URLSearchParamsInit, useSearchParams } from "react-router-dom";
import { cleanObject } from "../utils";

// export const useUrlQueryParam = <T extends string>(keys: T[]) => {
//   const [urlSearchParams, setURLSearchParams] = useSearchParams();
//   return [
//     //由于reduce每回都返回一个新的对象，所以可能导致监听该对象进行数据更新的hook出现死循环，所以用useMeno控制更新
//     //在参数改变的时候才需要更型
//     useMemo(() => {
//       return keys.reduce((pre, current) => {
//         return {
//           ...pre,
//           [current]: urlSearchParams.get(current) || "", //urlSearchParams.get可能存在null，pre是指定的[string]:string，导致类型错误
//         };
//       }, {} as { [key in T]: string }); //为对象指定理想类型（键为传入的数组指定的 ）
//       // }, {} as { [key: string]: string }),//为对象指定理想类型
//     }, [urlSearchParams]),
//     //Partial将类型的每一个转化为可选的
//     (param: Partial<{ [k in T]: unknown }>) => {
//       // urlSearchParams内部是迭代器
//       // Object.fromEntries解析迭代器为键值对返回
//       const obj = cleanObject({
//         ...Object.fromEntries(urlSearchParams),
//         ...param,
//       }) as URLSearchParamsInit;
//       setURLSearchParams(obj);
//     },
//   ] as const; //使用as const 断言将类型转化成理想类型（不指定推断出来的类型为：{}[]）
// };

export const useUrlQueryParam = <T extends string>(keys: T[]) => {
  const [urlSearchParams] = useSearchParams();
  const setURLSearchParams = useSetURLSearchParams();
  return [
    //由于reduce每回都返回一个新的对象，所以可能导致监听该对象进行数据更新的hook出现死循环，所以用useMeno控制更新
    //在参数改变的时候才需要更型
    useMemo(() => {
      return keys.reduce((pre, current) => {
        return {
          ...pre,
          [current]: urlSearchParams.get(current) || "", //urlSearchParams.get可能存在null，pre是指定的[string]:string，导致类型错误
        };
      }, {} as { [key in T]: string }); //为对象指定理想类型（键为传入的数组指定的 ）
      // }, {} as { [key: string]: string }),//为对象指定理想类型
    }, [urlSearchParams]),
    //Partial将类型的每一个转化为可选的
    (param: Partial<{ [k in T]: unknown }>) => {
      return setURLSearchParams(param);
    },
  ] as const; //使用as const 断言将类型转化成理想类型（不指定推断出来的类型为：{}[]）
};

/**
 * @description: 多个不同的useUrlQueryParam进行同时修改url的时候可以进行统一修改（避免多次调用导致前面的修改失效）
 * @return {*}
 */
export const useSetURLSearchParams = () => {
  const [urlSearchParams, setURLSearchParams] = useSearchParams();
  return (param: Partial<{ [k in string]: unknown }>) => {
    // urlSearchParams内部是迭代器
    // Object.fromEntries解析迭代器为键值对返回
    const obj = cleanObject({
      ...Object.fromEntries(urlSearchParams),
      ...param,
    }) as URLSearchParamsInit;
    setURLSearchParams(obj);
  };
};
